#!/usr/bin/env python
# -*- coding:utf-8 -*-
# @Time   : 2021/7/9 22:29
# @Author : cjw
import time
import uvicorn
from fastapi import FastAPI, Request
from fastapi.staticfiles import StaticFiles
from fastapi.middleware.cors import CORSMiddleware
from fastapi.exceptions import RequestValidationError, HTTPException
from fastapi.responses import PlainTextResponse

from tutorial import app03, app04, app05, app06, app07, app08
from coronavirus import application

app = FastAPI(title='FastAPI Tutorial',
              description='FastAPI教程 新冠病毒疫情跟踪器API接口文档，项目代码：https://gitee.com/caijianwei01/fastapi-tutorial',
              version='1.0.0',
              # dependencies= [], 定义全局依赖
              )

# FastAPI项目的静态文件配置
# mount表示将某个目录下一个完全独立的应用挂载过来，这个不会在API交互文档中显示
app.mount(path='/static', app=StaticFiles(directory='./coronavirus/static'), name='static')


# 全局错误处理: 重写HTTPException异常处理
# @app.exception_handler(HTTPException)
# async def http_exception_handler(request, exc):
#     """
#     :param request: 这个参数不能省
#     :param exc: 发生的异常
#     :return:
#     """
#     return PlainTextResponse(str(exc.detail), status_code=exc.status_code)


# 重写请求验证异常处理器
# @app.exception_handler(RequestValidationError)
# async def validation_exception_handler(request, exc):
#     return PlainTextResponse(str(exc.detail), status_code=400)

# 中间件：带yield的依赖的退出部分代码和后台任务，会在中间件之后运行
@app.middleware('http')
async def add_process_time_header(request: Request, call_next):
    # call_next: 将接收request请求作为参数
    start_time = time.time()
    response = await call_next(request)
    process_time = time.time() - start_time
    response.headers["X-Process-Time"] = str(process_time)
    return response


# CORS（跨域资源共享）配置
origins = [
    "http://localhost",
    "http://localhost:8080",
]
app.add_middleware(
    CORSMiddleware,
    allow_origins=origins,
    allow_credentials=True,
    allow_methods=['*'],
    allow_headers=['*'],
)

# 使用接口路由，prefix设置接口地址前缀，tags设置同类功能接口的标题名称显示
app.include_router(app03, prefix='/chapter03', tags=['第三章 请求参数和验证'])
app.include_router(app04, prefix='/chapter04', tags=['第四章 响应处理和FastAPI配置'])
app.include_router(app05, prefix='/chapter05', tags=['第五章 FastAPI的依赖注入系统'])
app.include_router(app06, prefix='/chapter06', tags=['第六章 安全、认证和授权'])
app.include_router(app07, prefix='/chapter07', tags=['第七章 FastAPI的数据库操作和多应用的目录结构设计'])
app.include_router(app08, prefix='/chapter08', tags=['第八章 中间件、CORS、后台任务、测试用例'])
app.include_router(application, prefix='/coronavirus', tags=['新冠病毒疫情跟踪器API'])

if __name__ == '__main__':
    # workers:设置进程的数量
    uvicorn.run('run:app', host='0.0.0.0', port=8000, reload=True, debug=True)
